package org.openkoala.koala.deploy.dialog;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.openkoala.koala.deploy.tree.RestWebServiceSelectionUI;
import org.openkoala.koala.deploy.webservice.pojo.MediaType;
import org.openkoala.koala.deploy.webservice.pojo.ParamType;
import org.openkoala.koala.deploy.webservice.pojo.RestWebServiceMethod;
import org.openkoala.koala.deploy.webservice.pojo.WebServiceType;
import org.openkoala.koala.deploy.webservice.util.AutoRestRuleUtils;

/**
 * 
 * 类    名：MethodConfigDialog.java
 *   
 * 功能描述：RESTful WebService发布接口方法配置界面。	
 *  
 * 作    者：xmfang(xinmin.fang@gmail.com)
 */
public class MethodConfigDialog extends Dialog {

	private RestWebServiceMethod restWebServiceMethod;
	private RestWebServiceSelectionUI restWebServiceSelectionUI;
	
	private Group httpMethodGroup;
	private Combo httpMethodCombo;
	
	private Group paramTypeGroup;
	private Combo paramTypeCombo;
	
	private Group pathUriGroup;
	private Text pathUriText;
	
	private Group producesMediaTypeGroup;

	private Group consumesMediaTypeGroup;

	public RestWebServiceMethod getRestWebServiceMethod() {
		return restWebServiceMethod;
	}

	public void setRestWebServiceMethod(RestWebServiceMethod restWebServiceMethod) {
		this.restWebServiceMethod = restWebServiceMethod;
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Method Details Config");
	}
	
	public MethodConfigDialog(Shell parentShell, RestWebServiceMethod restWebServiceMethod, RestWebServiceSelectionUI restWebServiceSelectionUI) {
		super(parentShell);
		this.restWebServiceMethod = restWebServiceMethod;
		this.restWebServiceSelectionUI = restWebServiceSelectionUI;
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		initializeDialogUnits(composite);
		GridData mainGridData = new GridData(500, 300);

		composite.setLayout(new GridLayout(1, false));
		composite.setLayoutData(mainGridData);
		
		initView(composite);
		return composite;
	}
	
	private void initView(Composite composite) {
		createHttpMethodGroup(composite);
		createParamTypeGroup(composite);
		createPathUriGroup(composite);
		createProducesMediaTypeGroup(composite);
		createConsumesMediaTypeGroup(composite);
	}
	
	private void createHttpMethodGroup(Composite parent) {
		GridData groupGridData = new GridData(GridData.FILL_HORIZONTAL);
		groupGridData.grabExcessHorizontalSpace = true;
		httpMethodGroup = new Group(parent, SWT.SHADOW_ETCHED_IN);
		httpMethodGroup.setText("HTTP Method");
		httpMethodGroup.setLayout(new GridLayout(1, false));
		httpMethodGroup.setLayoutData(groupGridData);
		
		httpMethodCombo = new Combo(httpMethodGroup, SWT.DROP_DOWN);
		for (WebServiceType httpMethodType : WebServiceType.values()) {
			httpMethodCombo.add(httpMethodType.name());
		}
		httpMethodCombo.setText(restWebServiceMethod.getType().name());
		
		httpMethodCombo.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				String httpMethodString = httpMethodCombo.getText();
				if (paramTypeCombo != null) {
					generateParamTypeItems(WebServiceType.getValueByString(httpMethodString));
					paramTypeCombo.setText(AutoRestRuleUtils.getDefaultParamType(WebServiceType.getValueByString(httpMethodString), restWebServiceMethod.getMethod()).name());
				}
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
	}
	
	private void createParamTypeGroup(Composite parent) {
		GridData groupGridData = new GridData(GridData.FILL_HORIZONTAL);
		groupGridData.grabExcessHorizontalSpace = true;
		paramTypeGroup = new Group(parent, SWT.SHADOW_ETCHED_IN);
		paramTypeGroup.setText("Parameter Transfer Type");
		paramTypeGroup.setLayout(new GridLayout(1, false));
		paramTypeGroup.setLayoutData(groupGridData);
		
		paramTypeCombo = new Combo(paramTypeGroup, SWT.DROP_DOWN);
		generateParamTypeItems(restWebServiceMethod.getType());
		if (restWebServiceMethod.getParamType() != null) {
			paramTypeCombo.setText(restWebServiceMethod.getParamType().name());
		} else {
			paramTypeCombo.setText("");
		}
		
		
		paramTypeCombo.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent event) {
				pathUriText.setText(
						AutoRestRuleUtils.generateUriPathByParameType(ParamType.getValueByString(paramTypeCombo.getText()), 
								restWebServiceMethod.getMethod()));
				
				for (Control child : consumesMediaTypeGroup.getChildren()) {
					child.dispose();
				}
				generateMediaTypesForChoose(consumesMediaTypeGroup, ParamType.getValueByString(paramTypeCombo.getText()), false);
				consumesMediaTypeGroup.layout();
			}
		});
	}
	
	private void generateParamTypeItems(WebServiceType httpMethod) {
		if (httpMethod == null) {
			return;
		}
		paramTypeCombo.removeAll();
		for (ParamType paramType : AutoRestRuleUtils.getParamTypes(httpMethod, restWebServiceMethod.getMethod())) {
			paramTypeCombo.add(paramType.name());
		}
	}
	
	private void createPathUriGroup(Composite parent) {
		GridData groupGridData = new GridData(GridData.FILL_HORIZONTAL);
		groupGridData.grabExcessHorizontalSpace = true;
		pathUriGroup = new Group(parent, SWT.SHADOW_ETCHED_IN);
		pathUriGroup.setText("Method Visit URI");
		pathUriGroup.setLayout(new GridLayout(1, false));
		pathUriGroup.setLayoutData(groupGridData);
		
		GridData textGridData = new GridData(GridData.FILL_HORIZONTAL);
		pathUriText = new Text(pathUriGroup, SWT.SINGLE | SWT.BORDER);
		pathUriText.setText(restWebServiceMethod.getUriPath());
		pathUriText.setLayoutData(textGridData);
	}
	
	private void createProducesMediaTypeGroup(Composite parent) {
		GridData groupGridData = new GridData(GridData.FILL_HORIZONTAL);
		groupGridData.grabExcessHorizontalSpace = true;
		producesMediaTypeGroup = new Group(parent, SWT.SHADOW_ETCHED_IN);
		producesMediaTypeGroup.setText("Produces Media Type");
		producesMediaTypeGroup.setLayout(new GridLayout(4, false));
		producesMediaTypeGroup.setLayoutData(groupGridData);
		
		generateMediaTypesForChoose(producesMediaTypeGroup, restWebServiceMethod.getParamType(), true);
	}
	
	private void createConsumesMediaTypeGroup(Composite parent) {
		GridData groupGridData = new GridData(GridData.FILL_HORIZONTAL);
		groupGridData.grabExcessHorizontalSpace = true;
		consumesMediaTypeGroup = new Group(parent, SWT.SHADOW_ETCHED_IN);
		consumesMediaTypeGroup.setText("Consumes Media Type");
		consumesMediaTypeGroup.setLayout(new GridLayout(4, false));
		consumesMediaTypeGroup.setLayoutData(groupGridData);

		generateMediaTypesForChoose(consumesMediaTypeGroup, restWebServiceMethod.getParamType(), false);
	}
	
	private void generateMediaTypesForChoose(Group group, ParamType paramType, boolean isProduces) {
		List<MediaType> mediaTypes = null;
		Set<MediaType> exitsMediaTypes = null;
		if (isProduces) {
			mediaTypes = AutoRestRuleUtils.getProducesMediaTypes();
			exitsMediaTypes = restWebServiceMethod.getProducesMediaTypes();
		} else {
			mediaTypes = AutoRestRuleUtils.getConsumesMediaTypesByParamType(paramType);
			exitsMediaTypes = restWebServiceMethod.getConsumesMediaTypes();
		}
		
		for (MediaType mediaType : mediaTypes) {
			Button mediaTypeCheckBox = new Button(group, SWT.CHECK);
			mediaTypeCheckBox.setText(mediaType.name());
			mediaTypeCheckBox.setData(mediaType);
			if (exitsMediaTypes != null && exitsMediaTypes.contains(mediaType)) {
				mediaTypeCheckBox.setSelection(true);
			}
		}
	}
	
	@Override
	protected void okPressed() {
		if (!httpMethodCombo.getText().isEmpty()) {
			restWebServiceMethod.setType(WebServiceType.getValueByString(httpMethodCombo.getText()));
		}
		if (!paramTypeCombo.getText().isEmpty()) {
			restWebServiceMethod.setParamType(ParamType.getValueByString(paramTypeCombo.getText()));
		}
		if (!pathUriText.getText().isEmpty()) {
			restWebServiceMethod.setUriPath(pathUriText.getText());
		}
		
		Set<MediaType> producesMediaTypes = new HashSet<MediaType>();
		for (Control checkBox : producesMediaTypeGroup.getChildren()) {
			Button producesMediaTypeCheckBox = (Button)checkBox;
			if (producesMediaTypeCheckBox.getSelection()) {
				producesMediaTypes.add((MediaType) producesMediaTypeCheckBox.getData());
			}
		}
		restWebServiceMethod.setProducesMediaTypes(producesMediaTypes);
		
		Set<MediaType> consumesMediaTypes = new HashSet<MediaType>();
		for (Control checkBox : consumesMediaTypeGroup.getChildren()) {
			Button consumesMediaTypeCheckBox = (Button) checkBox;
			if (consumesMediaTypeCheckBox.getSelection()) {
				consumesMediaTypes.add((MediaType) consumesMediaTypeCheckBox.getData());
			}
		}
		restWebServiceMethod.setConsumesMediaTypes(consumesMediaTypes);
		
		restWebServiceSelectionUI.refreshMethodLabel(restWebServiceMethod.getType().name(), restWebServiceMethod.getName());
		
		super.okPressed();
	}
	
}
